<template>
	<div class="test-container">
		<div id="edit-container" contenteditable class="edit-container"></div>
		<input type="text" id="emojiInput" />
		<button id="sendEmoji">发送</button>
	</div>
</template>

<script>
export default {
	name: 'TestContent',
	data() {
		return {
			lastEditRange: null // 定义最后光标对象
		};
	},
	mounted() {
		this.init();
	},
	methods: {
		init() {
			// const sendEmoji = document.getElementById('sendEmoji');
			// 编辑框点击事件
			document.getElementById('edit-container').onclick = function () {
				// 获取选定对象
				var selection = getSelection();
				// 设置最后光标对象
				this.lastEditRange = selection.getRangeAt(0);
			};

			// 编辑框按键弹起事件
			document.getElementById('edit-container').onkeyup = function () {
				// 获取选定对象
				var selection = getSelection();
				// 设置最后光标对象
				this.lastEditRange = selection.getRangeAt(0);
			};

			// 表情点击事件
			document.getElementById('sendEmoji').onclick = function () {
				// 获取编辑框对象
				var edit = document.getElementById('edit-container');
				// 获取输入框对象
				var emojiInput = document.getElementById('emojiInput');
				// 编辑框设置焦点
				edit.focus();
				// 获取选定对象
				var selection = getSelection();
				// 判断是否有最后光标对象存在
				if (this.lastEditRange) {
					// 存在最后光标对象，选定对象清除所有光标并添加最后光标还原之前的状态
					selection.removeAllRanges();
					selection.addRange(this.lastEditRange);
				}
				// 判断选定对象范围是编辑框还是文本节点
				if (selection.anchorNode.nodeName != '#text') {
					// 如果是编辑框范围。则创建表情文本节点进行插入
					var emojiText = document.createTextNode(emojiInput.value);

					if (edit.childNodes.length > 0) {
						// 如果文本框的子元素大于0，则表示有其他元素，则按照位置插入表情节点
						for (var i = 0; i < edit.childNodes.length; i++) {
							if (i == selection.anchorOffset) {
								edit.insertBefore(emojiText, edit.childNodes[i]);
							}
						}
					} else {
						// 否则直接插入一个表情元素
						edit.appendChild(emojiText);
					}
					// 创建新的光标对象
					const range = document.createRange();
					// 光标对象的范围界定为新建的表情节点
					range.selectNodeContents(emojiText);
					// 光标位置定位在表情节点的最大长度
					range.setStart(emojiText, emojiText.length);
					// 使光标开始和光标结束重叠
					range.collapse(true);
					// 清除选定对象的所有光标对象
					selection.removeAllRanges();
					// 插入新的光标对象
					selection.addRange(range);
				} else {
					// 如果是文本节点则先获取光标对象
					const range = selection.getRangeAt(0);
					// 获取光标对象的范围界定对象，一般就是textNode对象
					const textNode = range.startContainer;
					// 获取光标位置
					const rangeStartOffset = range.startOffset;
					// 文本节点在光标位置处插入新的表情内容
					textNode.insertData(rangeStartOffset, emojiInput.value);
					// 光标移动到到原来的位置加上新内容的长度
					range.setStart(textNode, rangeStartOffset + emojiInput.value.length);
					// 光标开始和光标结束重叠
					range.collapse(true);
					// 清除选定对象的所有光标对象
					selection.removeAllRanges();
					// 插入新的光标对象
					selection.addRange(range);
				}
				// 无论如何都要记录最后光标对象
				this.lastEditRange = selection.getRangeAt(0);
			};
		}
	}
};
</script>

<style scoped>
.test-container {
	position: fixed;
	width: 100%;
	bottom: 0;
}
.edit-container {
	width: calc(100vw -2px);
	height: 100px;
	border: 1px solid #000;
}
</style>
